//@ts-nocheck
/**
为撒需要合成事件？
磨平浏览器差异
实现对象复用,重用,减少辣鸡回收,提高性能
批量更新
*/
import {updateQueue} from './component';

export function addEvent(dom, eventType, listener){
  eventType = eventType.toLowerCase();
  // 在要绑定的DOM节点上挂载一个对象, 准备存放监听函数
  const eventStore = dom.eventStore || (dom.eventStore = {});
  eventStore[eventType] = listener;

  // 第1阶段是捕获, 第2个阶段是冒泡
  document.addEventListener(eventType.slice(2)/**onXxxx*/, dispatchEvent, false);
}

let syntheticEvent; // 合成事件
function dispatchEvent(event) {
  // eslint-disable-next-line prefer-const
  let {type, target} = event; // type=click target=button
  const eventType = 'on' + type; // onclick
  syntheticEvent = getSyntheticEvent(event);

  //在事件监听函数执行前进入批量监听模式
  updateQueue.isPending = true;

  // 模拟事件冒泡
  while (target){
    const {eventStore} = target;
    const listener = eventStore && eventStore[eventType]; // onclick
    if(listener){
      listener.call(target, syntheticEvent);
    }
    target = target.parentNode
  }

  // 等所有的监听函数执行完了, 清掉所有属性
  for (const key in syntheticEvent){
    if (key != 'persist') {
      delete syntheticEvent[key];
    }
  }

  //当事件处理函数执行完成后, 把批量更新模式改为false
  updateQueue.isPending = false;
  //执行批量更新, 就是把缓存的那些updater全部执行了
  updateQueue.batchUpdate()
}

function persist(){
  syntheticEvent = {persist}; // 赋了一个新对象, 等下清理的时候, 清理的就是这个对象
  /*
    const onClick = (syntheticEvent ) => { // ←syntheticEvent作为接受的参数 其值不会改变 即 引用地址不会改变
      console.log(syntheticEvent);
      syntheticEvent.persist(); // ← 如果不调用, 则只有↑有值

      // 这个时候已经开始清理 syntheticEvent了
      // 但由于调用了syntheticEvent.persist() 清理的不是我们onClick接受的syntheticEvent,而是新的syntheticEvent

      setInterval(() => {
        console.log(syntheticEvent); //← 这里的永远是onClick初次接受的syntheticEvent
      }, 1000);
    };
  */
}

function getSyntheticEvent(nativeEvent){
  if(!syntheticEvent){
    syntheticEvent = {persist};
  }
  syntheticEvent.nativeEvent = nativeEvent;
  syntheticEvent.currentTarget = nativeEvent.target;
  // 把原生事件对象上的方法和属性都拷贝到合成事件对象上
  for (const key in nativeEvent){
    if (typeof nativeEvent[key] == 'function') {
      syntheticEvent[key] = nativeEvent[key].bind(nativeEvent);
    } else {
      syntheticEvent[key] = nativeEvent[key];
    }
  }
  return syntheticEvent;
}
